/// @author: 善良的YWJ
/// @Created by shanliangdeYWJ on 2022/08/24
/// @file: todo_list.dart
/// @description:
/// ==================
/// flutter TodoMVC
/// ==================
/// @link [Github](https://github.com/shanliangdeYWJ)
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class TodoModel {
  TodoModel({
    required this.title,
    required this.done,
  });

  late String? title;
  late bool? done;

  TodoModel.fromJson(Map<String, dynamic> json) {
    title = json['title'];
    done = json['done'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['title'] = title;
    data['done'] = done;
    return data;
  }
}

List<Map<String, dynamic>> res = [
  {'title': 'star this repository', 'done': false},
  {'title': 'fork this repository', 'done': false},
  {'title': 'follow author', 'done': false},
  {'title': 'vue-element-admin', 'done': true},
  {'title': 'vue', 'done': true},
  {'title': 'element-ui', 'done': true},
  {'title': 'axios', 'done': true},
  {'title': 'webpack', 'done': true},
];

class TodoList extends StatefulWidget {
  const TodoList({Key? key}) : super(key: key);

  @override
  State<TodoList> createState() => _TodoListState();
}

List<TodoModel> todos = [];

class _TodoListState extends State<TodoList> {
  String visibility = 'all';

  int remaining = 0;
  bool isCompleted = false;
  bool isCheckAll = false;
  String _enteredKeyWord = '';

  /// 初始化todo
  void initTodos() {
    setState(() {
      todos = res.map((todo) => TodoModel.fromJson(todo)).toList();
    });
  }

  /// 过滤没完成的条数
  void setRemaining() {
    setState(() {
      remaining = todos.where((todo) => todo.done == false).toList().length;
    });
  }

  /// 任何一个完成就算完成
  void setActive() {
    setState(() {
      isCompleted = todos.any((todo) => todo.done == true);
    });
  }

  /// 全部完成才算完成
  void setIsCheckAll() {
    setState(() {
      isCheckAll =
          todos.isEmpty ? false : todos.every((todo) => todo.done == true);
    });
  }

  List<TodoModel> enteredKeyWordFilter(String enteredKeyWord) {
    List<TodoModel> result = [];
    if (enteredKeyWord.isEmpty) {
      result = todos;
    } else {
      result = todos
          .where((todo) =>
              todo.title!.toLowerCase().contains(enteredKeyWord.toLowerCase()))
          .toList();
    }
    return result;
  }

  List<TodoModel> filted(String filterStatus) {
    List<TodoModel> filtedList;

    switch (filterStatus) {
      case 'all':
        filtedList = enteredKeyWordFilter(_enteredKeyWord);
        break;
      case 'active':
        filtedList = enteredKeyWordFilter(_enteredKeyWord)
            .where((todo) => todo.done == false)
            .toList();
        break;
      case 'completed':
        filtedList = enteredKeyWordFilter(_enteredKeyWord)
            .where((todo) => todo.done == true)
            .toList();
        break;
      default:
        filtedList = enteredKeyWordFilter(_enteredKeyWord);
    }

    return filtedList;
  }

  @override
  void initState() {
    initTodos();
    setRemaining();
    setActive();

    if (kDebugMode) {
      print('todo ${todos.map((e) => e.toJson()).toList()}');
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTap: () {
        // 点击空白关闭软键盘
        FocusScope.of(context).requestFocus(FocusNode());
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text('TodoList'),
        ),
        body: Padding(
          padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
          child: Column(
            children: [
              TodoHeader(
                isCheckAll: isCheckAll,
                toggleAll: (value) {
                  setState(() {
                    isCheckAll = value;
                    todos.forEach((todo) => todo.done = value);
                  });
                  setRemaining();
                  setActive();
                },
                addTodo: (TodoModel todo) {
                  setState(() {
                    todos.add(todo);
                  });
                  setRemaining();
                  setIsCheckAll();
                },
                enteredKeyWordFilter: (String enteredKeyWord) {
                  setState(() {
                    _enteredKeyWord = enteredKeyWord;
                    enteredKeyWordFilter(enteredKeyWord);
                  });
                },
                onClear: (controller) {
                  setState(() {
                    controller.clear();
                  });
                },
              ),
              FilterBar(
                remaining: remaining,
                visibility: visibility,
                isCompleted: isCompleted,
                clearCompletedFunc: () {
                  setState(() {
                    // 把没完成的筛选出来赋值给列表就相当于删除了完成的
                    todos = todos.where((todo) => todo.done == false).toList();
                  });
                  setActive();
                  setRemaining();
                  setIsCheckAll();
                },
                fiiterFunc: (filterStatus) {
                  setState(() {
                    visibility = filterStatus;
                  });
                },
              ),
              Expanded(
                child: TodoMain(
                  todos: filted(visibility),
                  updateFunc: (TodoModel todo, bool done) {
                    setState(() {
                      int index = todos.indexOf(todo);
                      todos[index].done = done;
                    });
                    setRemaining();
                    if (kDebugMode) {
                      print('todo ${todos.map((e) => e.toJson()).toList()}');
                    }
                    setIsCheckAll();
                    setActive();
                  },
                  delFunc: (TodoModel todo) {
                    setState(() {
                      todos.remove(todo);
                    });
                    setRemaining();
                    setIsCheckAll();
                    setActive();
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class TodoHeader extends StatefulWidget {
  const TodoHeader({
    Key? key,
    required this.isCheckAll,
    required this.toggleAll,
    required this.addTodo,
    required this.enteredKeyWordFilter,
    required this.onClear,
  }) : super(key: key);

  final bool isCheckAll;
  final Function(bool value) toggleAll;
  final Function(TodoModel todo) addTodo;
  final Function(String enteredKeyWord) enteredKeyWordFilter;
  final Function(TextEditingController controller) onClear;

  @override
  State<TodoHeader> createState() => _TodoHeaderState();
}

class _TodoHeaderState extends State<TodoHeader> {
  late TextEditingController _controller;
  // FocusNode focusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 切换全部
        Padding(
          padding: const EdgeInsets.only(right: 8.0),
          child: Checkbox(
            value: widget.isCheckAll,
            onChanged: (bool? value) {
              widget.toggleAll(value!);
            },
          ),
        ),
        Expanded(
          // 输入框
          child: TextField(
            decoration: InputDecoration(
              prefixIcon: Icon(Icons.search),
              labelText: 'Todo',
              suffixIcon: InkWell(
                child: Icon(Icons.clear),
                onTap: () {
                  widget.onClear(_controller);
                  widget.enteredKeyWordFilter(_controller.text);
                },
              ),
            ),
            onChanged: (value) => widget.enteredKeyWordFilter(value),
            controller: _controller,
            onSubmitted: (String value) async {
              if (kDebugMode) {
                print('1111');
              }
              if (value.characters.isEmpty) {
                await showDialog<void>(
                  context: context,
                  builder: (BuildContext context) {
                    return AlertDialog(
                      title: const Text('Waring!'),
                      content: Text(
                        'Please Enter The Todo!',
                      ),
                      actions: <Widget>[
                        TextButton(
                          onPressed: () {
                            Navigator.pop(context);
                          },
                          child: const Text('OK'),
                        ),
                      ],
                    );
                  },
                );
              } else {
                TodoModel newTodo = TodoModel(title: value, done: false);

                widget.addTodo(newTodo);
              }

              _controller.clear();
              // FocusScope.of(context).requestFocus(focusNode);
            },
          ),
        ),
      ],
    );
  }
}

class FilterBar extends StatefulWidget {
  const FilterBar({
    Key? key,
    required this.visibility,
    required this.fiiterFunc,
    required this.remaining,
    required this.isCompleted,
    required this.clearCompletedFunc,
  }) : super(key: key);

  final String visibility;
  final Function(String filterStatus) fiiterFunc;
  final Function() clearCompletedFunc;
  final int remaining;
  final bool isCompleted;

  @override
  State<FilterBar> createState() => _FilterBarState();
}

class _FilterBarState extends State<FilterBar> {
  ButtonStyle _filterBarItemStyle(bool selected) {
    return ButtonStyle(
      backgroundColor: MaterialStateProperty.all<Color>(
        selected ? Theme.of(context).hoverColor : Colors.white,
      ),
      shape: MaterialStateProperty.all<RoundedRectangleBorder>(
        RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(6.0),
          side: BorderSide(
            color: Theme.of(context).primaryColor,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: Padding(
        padding:
            const EdgeInsets.only(left: 0.0, right: 0.0, top: 8.0, bottom: 8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // 切换的
            Padding(
              padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  TextButton(
                      style: _filterBarItemStyle(widget.visibility == 'all'),
                      onPressed: () {
                        widget.fiiterFunc('all');
                      },
                      child: Text('all')),
                  Padding(
                    padding: EdgeInsets.only(left: 5.0, right: 5.0),
                    child: TextButton(
                        style:
                            _filterBarItemStyle(widget.visibility == 'active'),
                        onPressed: () {
                          widget.fiiterFunc('active');
                        },
                        child: Text('active')),
                  ),
                  TextButton(
                      style:
                          _filterBarItemStyle(widget.visibility == 'completed'),
                      onPressed: () {
                        widget.fiiterFunc('completed');
                      },
                      child: Text('completed')),
                ],
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                // 剩下的
                SizedBox(
                  child: Text('${widget.remaining} items left'),
                ),
                SizedBox(width: 10.0),
                SizedBox(
                  child: GestureDetector(
                    child: Text(
                      widget.isCompleted ? 'Clear completed' : '',
                      style: TextStyle(
                        decoration: TextDecoration.underline,
                        decorationColor: Colors.red[900],
                      ),
                    ),
                    onTap: () {
                      widget.clearCompletedFunc();
                    },
                  ),
                ),
              ],
            ),
            // 清空todos
          ],
        ),
      ),
    );
  }
}

class TodoMain extends StatefulWidget {
  const TodoMain({
    Key? key,
    required this.todos,
    required this.updateFunc,
    required this.delFunc,
  }) : super(key: key);

  final List<TodoModel> todos;
  final Function(TodoModel todo, bool done) updateFunc;
  final Function(TodoModel todo) delFunc;

  @override
  State<TodoMain> createState() => _TodoMainState();
}

class _TodoMainState extends State<TodoMain> {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: ListView(
        padding: const EdgeInsets.symmetric(vertical: 8.0),
        children: widget.todos.map((todo) {
          return TodoItem(
            todo: todo,
            updateFunc: widget.updateFunc,
            delFunc: widget.delFunc,
          );
        }).toList(),
      ),
    );
  }
}

class TodoItem extends StatefulWidget {
  const TodoItem({
    Key? key,
    required this.todo,
    required this.updateFunc,
    required this.delFunc,
  }) : super(key: key);

  final TodoModel todo;
  final Function(TodoModel todo, bool done) updateFunc;
  final Function delFunc;

  @override
  State<TodoItem> createState() => _TodoItemState();
}

class _TodoItemState extends State<TodoItem> {
  late TextEditingController _todoItemTextFieldController;

  @override
  void initState() {
    super.initState();
    _todoItemTextFieldController = TextEditingController();
  }

  @override
  Widget build(BuildContext context) {
    return ListTile(
      // onTap: () {
      //   // widget.todo.done = !(widget.todo.done!);
      //   widget.updateFunc(widget.todo, !(widget.todo.done!));
      // },
      leading: Checkbox(
        value: widget.todo.done,
        onChanged: (bool? value) {
          // widget.todo.done = value;
          widget.updateFunc(widget.todo, value!);
        },
      ),
      title: GestureDetector(
        onDoubleTap: () {
          showDialog<void>(
            context: context,
            builder: (BuildContext context) {
              return AlertDialog(
                title: const Text('Waring!'),
                content: TextField(
                  controller: _todoItemTextFieldController,
                  decoration: InputDecoration(
                    labelText: widget.todo.title,
                  ),
                ),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.pop(context);
                    },
                    child: const Text('Cancel'),
                  ),
                  TextButton(
                    onPressed: () {
                      widget.todo.title =
                          _todoItemTextFieldController.value.text;
                      widget.updateFunc(widget.todo, widget.todo.done!);
                      _todoItemTextFieldController.clear();
                      Navigator.pop(context);
                    },
                    child: const Text('Ok'),
                  ),
                ],
              );
            },
          );
        },
        child: Text(
          widget.todo.title!,
          style: (widget.todo.done!)
              ? TextStyle(
                  fontSize: 14,
                  color: Colors.black54,
                  decoration: TextDecoration.lineThrough,
                )
              : null,
        ),
      ),
      trailing: IconButton(
        icon: Icon(
          Icons.delete_forever_rounded,
          color: Colors.brown,
        ),
        onPressed: () {
          widget.delFunc(widget.todo);
        },
      ),
    );
  }
}
